$OpenBSD: patch-src_first_network_device_c,v 1.3 2017/02/07 18:22:28 jasper Exp $

https://github.com/i3/i3status/pull/197

--- src/first_network_device.c.orig	Sat Jan 21 16:00:31 2017
+++ src/first_network_device.c	Mon Feb  6 22:18:13 2017
@@ -3,9 +3,23 @@
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <ifaddrs.h>
+#ifdef __OpenBSD__
+#include <sys/types.h>
+#include <sys/sockio.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_ioctl.h>
+#endif
 
 #include "i3status.h"
 
+#ifdef __linux__
+#define LOOPBACK_DEV "lo"
+#else
+#define LOOPBACK_DEV "lo0"
+#endif
+
 static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) {
     FILE *fp;
     char buf[1024];
@@ -37,6 +51,7 @@ static bool sysfs_devtype(char *dest, size_t n, const 
 }
 
 static net_type_t iface_type(const char *ifname) {
+#ifdef __linux__
     char devtype[32];
 
     if (!sysfs_devtype(devtype, sizeof(devtype), ifname))
@@ -52,6 +67,51 @@ static net_type_t iface_type(const char *ifname) {
         return NET_TYPE_OTHER;
 
     return NET_TYPE_OTHER;
+#elif __OpenBSD__
+    /*
+     *First determine if the device is a wireless device by trying two ioctl(2)
+     * commands against it. If either succeeds we can be sure it's a wireless
+     * device.
+     * Otherwise we try another ioctl(2) to determine the interface media. If that
+     * fails it's not an ethernet device eiter.
+     */
+    struct ifreq ifr;
+    struct ieee80211_bssid bssid;
+    struct ieee80211_nwid nwid;
+    struct ifmediareq ifmr;
+
+    int s, ibssid, inwid;
+
+    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+        return NET_TYPE_OTHER;
+
+    memset(&ifr, 0, sizeof(ifr));
+    ifr.ifr_data = (caddr_t)&nwid;
+    (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr);
+
+    memset(&bssid, 0, sizeof(bssid));
+    strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name));
+    ibssid = ioctl(s, SIOCG80211BSSID, &bssid);
+
+    if (ibssid == 0 || inwid == 0) {
+        close(s);
+        return NET_TYPE_WIRELESS;
+    }
+
+    (void) memset(&ifmr, 0, sizeof(ifmr));
+    (void) strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+
+    if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+        close(s);
+        return NET_TYPE_OTHER;
+    } else {
+        close(s);
+        return NET_TYPE_ETHERNET;
+    }
+#else
+#error Missing implementation to determine interface type.
+#endif
 }
 
 const char *first_eth_interface(const net_type_t type) {
@@ -69,15 +129,20 @@ const char *first_eth_interface(const net_type_t type)
     for (addrp = ifaddr;
          addrp != NULL;
          addrp = addrp->ifa_next) {
-        if (strncasecmp("lo", addrp->ifa_name, strlen("lo")) == 0)
+        if (strncasecmp(LOOPBACK_DEV, addrp->ifa_name, strlen(LOOPBACK_DEV)) == 0)
             continue;
         if (addrp->ifa_addr == NULL)
             continue;
+#ifdef __OpenBSD__
+        if (addrp->ifa_addr->sa_family != AF_LINK)
+            continue;
+#else
         // Skip PF_PACKET addresses (MAC addresses), as they are present on any
         // ethernet interface.
         if (addrp->ifa_addr->sa_family != AF_INET &&
             addrp->ifa_addr->sa_family != AF_INET6)
             continue;
+#endif /* !__OpenBSD__ */
         // Skip this interface if it is a wireless interface.
         iftype = iface_type(addrp->ifa_name);
         if (iftype != type)
